/**
 * @author: Gene
 * @age: 永远18岁的美少年
 * @Email： yangjianyun@58.com
 * @date: 2021-11-30 22:14:15
 * @description:  typescript 的基本类型
 */
let married: boolean = true
let age: number = 0
let first_name: string = "Gene"
let arr1: number[] = [1, 2, 3]
let arr2: Array<number> = [4, 5, 6]

// 元组类型 tuple元组: 表示 已知数量 和 类型的一个数组. 类型和数量固定,不能多写, 也不能少写
let AA: [string, number] = ['Gene', 2]

//  1.普通枚举类型
enum GenderEnum {
    GIRL,
    BOY
}

console.log(GenderEnum.GIRL);

// 2.常量枚举类型
const enum Colors {
    RED, YELLOW, BLUE
}

let myColor = [Colors.RED, Colors.YELLOW, Colors.BLUE]

// 3. 任意类型  any 类型  => 如果变量定义为 any类型, 那么久跟 js 差不多了, 不进行类型检查了.
// let element: (HTMLElement | null) = document.getElementById('root')
// 非空断言
// element!.style.color = "red"

//4. null 和 undefined 类型. 是其他类型的子类型
// 如果說 strictNullChecks 的值為 tru, 则不能把  null ,undefined 赋值给其他类型
let x: number | undefined | null;
x = 1
x = undefined
x = null

// 5. never 类型 代表不会出现的值
// 5.1 作为不会返回的函数的返回值  类型
function error(message: string): never {
    throw new Error("啊哦, 报错了呢") // 直接异常结束了, 下面就不会执行了,也永远不会有返回值
    console.log("ok");
}

// 5.2 死循环, 函数是never类型
function loop(): never {
    while (true) {

    }
}

// 5.3 never 永远走不到的情景
function fn(x: number | string) {
    if (typeof x === "number") { // 肯定 number 类型保护
        console.log(x);
    } else if (typeof x === "string") { // 肯定 string 类型保护
        console.log(x);
    } else {
        console.log(x); // 这里就是 never了, 永远走不到
    }
}


// void 和 never 的区别
// void 代表没有任何类型, 如果一个函数,没有返回值, 那么就是 void 类型
// void 可以被赋值为 null 和 undefined,  但是never 是不能包含任何类型的.
// 如果一个函数,返回类型 为 void, 能正常执行, 但是返回 never 的函数, 无法正常执行
function greeting(): void {
    return undefined
}

// Symbol 类型
const s1 = Symbol('key')
const s2 = Symbol('key')
// console.log(s1 === s2);

// BigInt 大数字类型, 如果要用这个类型, 在 tsconfig.json中 的lib中,也需要 ESNext 这个库
const max = Number.MAX_SAFE_INTEGER;
console.log(max + 1 === max + 2);


///  类型推导
let uname;
uname = 1

let uname2 = "Gene" // uname2 会自动推导成 string 类型


//  包装对象 wrapper object
// 原始类型  对象类型


/** -------------- 联合类型  ------------  */
// 联合类型,只能访问两个类型 共有的方法
let name3: string | number
console.log(name3!.toString());

/** -------------- 类型断言 --------------*/
let name4: string | number
console.log((name4! as number).toFixed());
console.log((name4! as string).length);
// 双重断言
console.log((name4! as any as boolean));


/** ======== 字面量类型  和 类型字面量 ============*/
// 1. 字面量类型: => 一个字面量, 即一个字符串,值 就是一个类型
const up: "Up" = "Up"
const down: "Down" = "Down"
const left: "Left" = "Left"
const right: "Right" = "Right"
const value: 1 = 1
// 可以实现枚举的效果
type Direction = "Up" | "Down" | "Left"

function go(direction: Direction) {

}

go("Left")

// 2. 类型字面量.  类型字面量的写法,很像一个对象
type Person = {
    name: string,
    age: number
}
let p: Person = {
    name: "Gene",
    age: 10
}


/** ========= 字符串字面量 和 联合类型的区别 ============*/
type T1 = '1' | '2' | '3'  // 这叫字符串字面量. T1 只能是这三个其中一个
type T2 = string | number | boolean // 联合类型,可以是这三种其中的一种